#pragma once

#include "templatevectorspecialsort.h"

//template <class KEY, class VALUE>
//class TemplateTable : public TemplateVector<VALUE>
//{
//protected:
//	TemplateVector<KEY> m_keys;
//public:
//	int keyIndex(const KEY & a_key)
//	{
//		return m_keys.indexOfWithBinarySearch(a_key);
//	}
//	VALUE * getByKey(const KEY & a_key)
//	{
//		int index = m_keys.indexOfWithBinarySearch(a_key);
//		return (index < 0)?0:&get(index);
//	}
//	KEY getKey(const int & a_index)
//	{
//		return m_keys.get(a_index);
//	}
//	void replaceKeyWith(const int & a_keyIndex, const KEY & a_newKey)
//	{
//		m_keys.set(a_keyIndex, a_newKey);
//	}
//	void add(const KEY & a_key, const VALUE & a_value)
//	{
//		int index = m_keys.indexOf(a_key);
//		if(index < 0)
//		{
//			// insertion sort
//			for(index = 0; index < size() && m_keys.get(index) < a_key; ++index);
//			m_keys.insert(index, a_key);
//			insert(index, a_value);
//		}
//		else
//		{
//			set(index, a_value);
//		}
//	}
//	void release()
//	{
//		m_keys.release();
//		TemplateVector<VALUE>::release();
//	}
//};

template <class KEY, class VALUE>
class TemplateTable : public TemplateVector<VALUE>
{
protected:
	TemplateVectorSpecialSort<KEY> m_keys;
public:
	void setKeySortingMechanism(
		typename TemplateVectorSpecialSort<KEY>::BinaryOperator const & a_sortMechanism, 
		typename TemplateVectorSpecialSort<KEY>::BinaryOperator const & a_equalTo)
	{
		m_keys.setSortingMechanism(a_sortMechanism, a_equalTo);
	}
	int keyIndex(const KEY & a_key)
	{
		return m_keys.indexOfSortedInsert(a_key);
	}
	VALUE * getByKey(const KEY & a_key)
	{
		int index = m_keys.indexOfWithBinarySearch(a_key);//SortedInsert(a_key);
		return (index < 0)?0:&get(index);
	}
	KEY getKey(const int & a_index)
	{
		return m_keys.get(a_index);
	}
	int getKeyCount()
	{
		return m_keys.size();
	}
	void replaceKeyWith(const int & a_keyIndex, const KEY & a_newKey)
	{
		m_keys.set(a_keyIndex, a_newKey);
	}
	void add(const KEY & a_key, const VALUE & a_value)
	{
		int index = m_keys.indexOfSortedInsert(a_key);
		m_keys.insert(index, a_key);
		insert(index, a_value);
	}
	void addNoDuplicates(const KEY & a_key, const VALUE & a_value)
	{
		int index = m_keys.indexOfSortedInsert(a_key);
		// if the key is a duplicate
		if(index >= 0 && index < m_keys.size()
		&& m_keys.equalTo(a_key, m_keys.get(index)))
		{
			// don't add duplicates, replace.
			set(index, a_value);
		}
		else
		{
			m_keys.insert(index, a_key);
			insert(index, a_value);
		}
	}
	void release()
	{
		m_keys.release();
		TemplateVector<VALUE>::release();
	}
};

template <class VALUE>
class TemplateNameTable : public TemplateTable<char*, VALUE>
{
protected:
	/** @return true if a comes before b*/
	static bool S_LessThan(char * const & a, char * const & b)
	{
		for(int i = 0; a[i] || b[i]; ++i)
		{
			if(a[i] < b[i])	return true;
			if(a[i] > b[i])	return false;
		}
		return false;
	}
	static bool S_EqualTo(char* const & a, char* const & b)
	{
		int i;
		for(i = 0; a[i] == b[i] && a[i]; ++i);
		return !a[i] && !b[i];
	}
public:
	TemplateNameTable()
	{
		m_keys.setSortingMechanism(S_LessThan, S_EqualTo);
	}
};